package model;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.log4j.Logger;

public class KeyAction extends KeyAdapter
{
	List<ActionEventWrapper> actionEventList;
	Logger logger;

	public KeyAction(List<ActionEventWrapper> actionEventList)
	{
		this.actionEventList = actionEventList;
		logger = Logger.getLogger(this.getClass().getName());
	}

	@Override
	public void keyPressed(KeyEvent ke)
	{
		String commandSuffix = "_pressed";
		performKeyEvent(ke, commandSuffix);

	}

	@Override
	public void keyReleased(KeyEvent ke)
	{
		String commandSuffix = "_released";
		//Don't do keyRelased for commands with second-key modifiers
		if(ke.getModifiers() <= 0){
			performKeyEvent(ke, commandSuffix);
		}
	}

	private void performKeyEvent(KeyEvent ke, String commandSuffix)
	{

		for (ActionEventWrapper a : actionEventList)
		{

			int keyEvent = (Integer) a.getActionEvent().getSource();
			int[] modifiers = a.getKeyModifiers();
			Object[] methodParams = a.getMethodParams();
			Object sourceClass = a.getSource();
			String commandText = a.getActionEvent().getActionCommand();
			if (keyEvent == ke.getKeyCode())
			{
				if (matchedModifiers(ke, modifiers))
					try
				{
						Class<?> paramTypes[] = new Class<?>[methodParams.length];
						for (int i = 0; i < methodParams.length; i++)
						{
							paramTypes[i] = methodParams[i].getClass();
						}

						Class<?> cls = sourceClass.getClass();
						Method method = cls.getMethod(commandText + commandSuffix, paramTypes);
						method.invoke(sourceClass, methodParams);
				}
				catch (Exception e)
				{
					logger.error("Error invoking command " + "[" + commandText + commandSuffix + "]" + " on " + sourceClass.getClass().getName());
				}
			}
		}
	}

	/**
	 * Checks for key modifiers like shift + key, ctrl + key, etc
	 * 
	 * @param keyEvent
	 * @param modifiers
	 * @return
	 */
	private boolean matchedModifiers(KeyEvent keyEvent, int[] modifiers)
	{
		boolean matchedMask = false;
		int sourceModifiers = keyEvent.getModifiers();
		
		//check for used modifiers, return false any are present
		//TODO: move this to it's own method, store list of game modifiers and pass it in separately
		
		if (modifiers.length == 0)
		{
			if ((sourceModifiers & KeyEvent.SHIFT_MASK) == 0)
			{
				matchedMask = true;
			}
		}
		else
		{
			for (int i = 0; i < modifiers.length; i++)
			{
				
				if ((sourceModifiers & modifiers[i]) > 0)
				{
					matchedMask = true;
				}
			}
		}
		return matchedMask;
	}

}
